home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / !FednetCmp / c / Main < prev    next >
Encoding:
Text File  |  2003-11-06  |  11.8 KB  |  382 lines

  1. /*
  2.  *  FednetCmp - Fednet file compression/decompression
  3.  *  Main application skeleton
  4.  *  Copyright (C) 2001  Chris Bazley
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public Licence as published by
  8.  *  the Free Software Foundation; either version 2 of the Licence, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public Licence for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public Licence
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* ANSI library files */
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #ifdef DEBUG
  25. #include <stdio.h>
  26. #endif
  27. #include <stdbool.h>
  28. #include <signal.h>
  29. #include <ctype.h>
  30.  
  31. /* RISC OS library files */
  32. #include "kernel.h"
  33. #include "toolbox.h"
  34. #include "event.h"
  35. #include "flex.h"
  36. #include "wimp.h"
  37. #include "wimplib.h"
  38.  
  39. /* My library files */
  40. #include "err.h"
  41. #include "msgtrans.h"
  42. #include "hourglass.h"
  43. #include "FedCompMT.h"
  44. #include "Macros.h"
  45. #include "Loader.h"
  46. #include "SFformats.h"
  47. #include "ViewsMenu.h"
  48. #include "RoundRobin.h"
  49. #include "LoadSaveMT.h"
  50. #include "InputFocus.h"
  51.  
  52. /* Local headers */
  53. #include "FNCIconbar.h"
  54. #include "FNCMenu.h"
  55. #include "Utils.h"
  56. #include "Main.h"
  57. #include "PreQuit.h"
  58. #include "Scan.h"
  59. #include "FilePerc.h"
  60.  
  61. #define WimpVersion    310
  62.  
  63. /* This is the MINIMUM amount of work we do per null poll (though the
  64.    maximum shouldn't be too much greater, since our RoundRobinHandler
  65.    is well written). We null poll as often as possible, like a program
  66.    running under the TaskWindow module. The event mask is used (rather
  67.    than Wimp_PollIdle) to avoid receiving unnecessarily null events.  */
  68. #define NULL_TIME_SLICE 10
  69.  
  70. _kernel_oserror shared_err_block = {255, ""};
  71. char taskname[32];
  72. bool multi_saveboxes = false;
  73. bool quit_parse_cl = false;
  74. ObjectId last_savebox = NULL_ObjectId;
  75. int timeslice = NULL_TIME_SLICE;
  76. const int fednet_filetypes[11] = {FILETYPE_FEDNET, FILETYPE_POLYOBJS, FILETYPE_BASEMAP, FILETYPE_BASEOBJS, FILETYPE_LEVELMAP, FILETYPE_LEVELOBJS, FILETYPE_SKYCOLS, FILETYPE_MISSION, FILETYPE_PLANETS, FILETYPE_MAPTILES, FILETYPE_ANIMS};
  77.  
  78. static  WimpPollBlock poll_block;
  79. static  IdBlock       id_block;
  80.  
  81. /* ----------------------------------------------------------------------- */
  82. /*                       Function prototypes                               */
  83.  
  84. static WimpMessageHandler WimpPreQuit_handler, WimpQuit_handler;
  85. static ToolboxEventHandler autocreate_handler, error_handler;
  86. static void initialise(void);
  87. static void process_arguments(int argc, char *argv[]);
  88. static LoaderFinishedHandler quickdecompress_handler;
  89. static LoaderFileHandler dummy_loader;
  90. #ifdef DEBUG
  91. static void show_budge(void);
  92. #endif
  93. static void simple_exit(_kernel_oserror *e);
  94. static void load_cl_files(int argc, char *argv[]);
  95.  
  96. /* ----------------------------------------------------------------------- */
  97. /*                         Public functions                                */
  98.  
  99. int main(int argc, char *argv[])
  100. {
  101.  
  102.   process_arguments(argc, argv);
  103.   initialise();
  104.   load_cl_files(argc, argv);
  105.   if(quit_parse_cl)
  106.     WimpQuit_handler(NULL, NULL);
  107.  
  108.   /*
  109.    * poll loop
  110.    */
  111.  
  112.   while (TRUE) {
  113.     int event_code;
  114.     event_poll(&event_code, &poll_block, NULL);
  115.   }
  116. }
  117.  
  118. /* ----------------------------------------------------------------------- */
  119. /*                         Private functions                               */
  120.  
  121. static int WimpPreQuit_handler(WimpMessage *message, void *handle)
  122. {
  123.   int th;
  124.   if(message->hdr.size < 20 || message->data.words[0] == 0)
  125.     th = message->hdr.sender; /* shutdown in progress */
  126.   else
  127.     th = 0; /* just our task */
  128.  
  129.   /* If function returns false then unsaved data */
  130.   if(!TRY_QUIT(th)) {
  131.  
  132.     /* Object by acknowledging message */
  133.     message->hdr.your_ref = message->hdr.my_ref;
  134.     RE(wimp_send_message(Wimp_EUserMessageAcknowledge, message, message->hdr.sender, NULL, NULL))
  135.   }
  136.   return 1; /* claim event */
  137. }
  138.  
  139. /* ----------------------------------------------------------------------- */
  140.  
  141. static int WimpQuit_handler(WimpMessage *message,void *handle)
  142. {
  143.   exit(EXIT_SUCCESS);
  144.   return 1; /* claim event */
  145. }
  146.  
  147. /* ----------------------------------------------------------------------- */
  148.  
  149. static int autocreate_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  150. {
  151.   /* Catch auto-created objects and initialise handlers etc. */
  152.   ToolboxObjectAutoCreatedEvent *toace = (ToolboxObjectAutoCreatedEvent *)event;
  153.   if (strcmp(toace->template_name, "Menu") == 0) {
  154.     Menu_initialise(id_block->self_id);
  155.     return 1; /* claim event */
  156.   }
  157.   if (strcmp(toace->template_name, "PreQuit") == 0) {
  158.     PreQuit_initialise(id_block->self_id);
  159.     return 1; /* claim event */
  160.   }
  161.   if (strcmp(toace->template_name, "Iconbar") == 0) {
  162.     Iconbar_initialise(id_block->self_id);
  163.     return 1; /* claim event */
  164.   }
  165.   return 0; /* event not handled */
  166. }
  167.  
  168. /* ----------------------------------------------------------------------- */
  169.  
  170. static int error_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  171. {
  172.   ToolboxErrorEvent *totee = (ToolboxErrorEvent *)event;
  173. #ifdef DEBUG
  174.   char str[256];
  175.   sprintf(str, "report errnum: %x errmess: %s", totee->errnum, totee->errmess);
  176.   _kernel_oscli(str);
  177. #endif
  178.   if(totee->errnum == 0x80b633 || totee->errnum == 0x131c3 || totee->errnum == 255) /* "To save drag...", locked file, user error */
  179.     err_report(totee->errnum, totee->errmess);
  180.   else
  181.     err_complain(totee->errnum, totee->errmess);
  182.   return 1;
  183. }
  184.  
  185. /* ----------------------------------------------------------------------- */
  186.  
  187. static void initialise(void)
  188. {
  189.   int    toolbox_events = 0,
  190.          wimp_messages = 0,
  191.          wimp_version;
  192.          
  193.   hourglass_on();
  194.  
  195. #ifdef DEBUG
  196.   atexit(show_budge);
  197. #endif
  198.  
  199.   /*
  200.    * Prevent termination on SIGINT (we use the escape key ourselves)
  201.    */
  202.    signal(SIGINT, SIG_IGN);
  203.  
  204.   /*
  205.    * register ourselves with the Toolbox.
  206.    */
  207.  
  208.   {
  209.     _kernel_oserror *e = toolbox_initialise (0, WimpVersion, &wimp_messages, &toolbox_events, "<FednetCmpRes$Dir>",msgs_get_descriptor(), &id_block, &wimp_version, 0, 0);
  210.     if(e != NULL)
  211.       simple_exit(e);
  212.   }
  213.   strncpy(taskname, msgs_lookup("_TaskName"), sizeof(taskname)-1);
  214.   err_set_taskname(taskname, (wimp_version >= 321));
  215.  
  216.   /*
  217.    * initialise the flex library
  218.    */
  219.  
  220.   flex_init(taskname, (int *)msgs_get_descriptor(), 0); /* (use Wimpslot and own messages file) */
  221.   flex_set_budge(1); /* allow budging of flex when heap extends */
  222.   
  223.   /*
  224.    * initialise the event library.
  225.    */
  226.  
  227.   event_initialise (&id_block);
  228.   event_set_mask (Wimp_Poll_NullMask |
  229.                   Wimp_Poll_PointerLeavingWindowMask |
  230.                   Wimp_Poll_PointerEnteringWindowMask |
  231.                   Wimp_Poll_KeyPressedMask | /* Dealt with by Toolbox */
  232.                   Wimp_Poll_LoseCaretMask |
  233.                   Wimp_Poll_GainCaretMask);
  234.  
  235.   EF(event_register_toolbox_handler(-1, Toolbox_ObjectAutoCreated, autocreate_handler, 0));
  236.   EF(event_register_toolbox_handler(-1, Toolbox_Error, error_handler, 0));
  237.   EF(event_register_message_handler(Wimp_MPreQuit, WimpPreQuit_handler, 0));
  238.   EF(event_register_message_handler(Wimp_MQuit,WimpQuit_handler,0));
  239.  
  240.   EF(InputFocus_initialise());
  241.   EF(RoundRobin_initialise(timeslice));
  242.  
  243.   /*
  244.    * initialise the Loader library.
  245.    */
  246.  
  247.   EF(loader_initialise(0));
  248.  
  249.   /* Capture Filer double-clicks of compressed files (type &154) and decompress them in-situ */
  250.   EF(loader_register_listener(LISTENER_CLAIM|LISTENER_FILEONLY, FILETYPE_FEDNET, NULL, NULL, dummy_loader, quickdecompress_handler, NULL));
  251.  
  252.   EF(ViewsMenu_create());
  253.   
  254.   hourglass_off();
  255. }
  256.  
  257. /* ----------------------------------------------------------------------- */
  258.  
  259. static void load_cl_files(int argc, char *argv[])
  260. {
  261.   /*
  262.    * Load any files specified as command-line arguments
  263.    */
  264.   
  265.   for(int i = 1; i < argc; i++) {
  266.     /* anything without a '-' in front is interpreted as a file to decompress */
  267.     if (*argv[i] != '-' && (i < 2 || !ViewsMenu_strcmp_nc(argv[i-1], "-timeslice"))) {
  268.  
  269.       /* get filetype (can't use _kernel_osfile as it doesn't return R6) */
  270.       _kernel_swi_regs regs;
  271.       regs.r[0] = 23;
  272.       regs.r[1] = (int)argv[i];
  273.       if(!E(_kernel_swi(OS_File, ®s, ®s))) {
  274.         /* Does filetype match any known Fednet type? */
  275.         for(int j = 0; j < sizeof(fednet_filetypes)/sizeof(int); j++) {
  276.           if(regs.r[6] == fednet_filetypes[j]) {
  277.             if(!quit_parse_cl)
  278.               /* Start a multi-tasking decompression operation */
  279.               quickdecompress_handler(argv[i], 0, NULL, regs.r[6], NULL);
  280.             else {
  281.               /* A multi-tasking decompression is incompatible with '-quit' */
  282.               _kernel_oserror *err;
  283.               void *buffer_anchor;
  284.               err = perc_operation(FILEPERC_OP_DECOMP, argv[i], 0, &buffer_anchor);
  285.               if(err != NULL)
  286.                 err_report(err->errnum, msgs_lookup_sub1("LoadFail", err->errmess));
  287.               else {
  288.                 err = perc_operation(FILEPERC_OP_SAVE, argv[i], FILETYPE_DATA, &buffer_anchor);
  289.                 if(err != NULL)
  290.                   err_report(err->errnum, msgs_lookup_sub1("SaveFail", err->errmess));
  291.               }
  292.             }
  293.             break;
  294.           }
  295.         }
  296.       }
  297.     }
  298.   } /* next parameter */
  299. }
  300.  
  301. /* ----------------------------------------------------------------------- */
  302.  
  303. static void simple_exit(_kernel_oserror *e)
  304. {
  305.   /* Limited amount we can do with no messages file... */
  306.   wimp_report_error(e, Wimp_ReportError_Cancel, "FednetCmp");
  307.   exit(EXIT_FAILURE);
  308. }
  309.  
  310. /* ----------------------------------------------------------------------- */
  311.  
  312. static void process_arguments(int argc, char *argv[])
  313. {
  314.   /*
  315.    * Look at command-line parameters
  316.    */
  317.  
  318.   for(int i = 1; i < argc; i++) {
  319.     if(ViewsMenu_strcmp_nc(argv[i], "-quit"))
  320.       quit_parse_cl = true;
  321.     else {
  322.       if(ViewsMenu_strcmp_nc(argv[i], "-multi"))
  323.         multi_saveboxes = true;
  324.       else {
  325.         if(ViewsMenu_strcmp_nc(argv[i], "-timeslice") && i+1 < argc) {
  326.           for(int c = 0; c < strlen(argv[i+1]); c++) {
  327.             if(!isdigit(argv[i+1][c])) {
  328.               strcpy(shared_err_block.errmess, "Bad command line parameters");
  329.               simple_exit(&shared_err_block);
  330.             }
  331.           }
  332.           sscanf(argv[i+1], "%d", ×lice);
  333.         } else {
  334.           if(*argv[i] == '-') {
  335.             /* Catches unknown options, but not time values or file paths */
  336.             strcpy(shared_err_block.errmess, "Bad command line parameters");
  337.             simple_exit(&shared_err_block);
  338.           }
  339.         }
  340.       }
  341.     }
  342.   }
  343. }
  344.  
  345. /* ----------------------------------------------------------------------- */
  346.  
  347. static void quickdecompress_handler(char *file_path, bool data_saved, flex_ptr buffer, int filetype, void *handle)
  348. {
  349.   /* Deals with Filer double-clicks on compressed files */
  350.   ObjectId process_id = Scan_create(file_path, file_path, false, 0);
  351.   if(process_id != NULL_ObjectId)
  352.     RE(toolbox_show_object(0, process_id, Toolbox_ShowObject_Centre, 0, 0, 0));
  353. }
  354.  
  355. /* ----------------------------------------------------------------------- */
  356.  
  357. static _kernel_oserror *dummy_loader(char *filepath, flex_ptr buffer_anchor)
  358. {
  359.   return NULL;
  360. }
  361.  
  362. /* ----------------------------------------------------------------------- */
  363.  
  364. //static _kernel_oserror *load_compressed(char *filepath, flex_ptr buffer_anchor)
  365. //{
  366. //  /* Simple veneer onto multi-tasking decompression function */
  367. //  bool timeup = false;
  368. //  void *handle = NULL;
  369. //  return load_compressedM(filepath, buffer_anchor, &timeup, &handle);
  370. //}
  371.  
  372. #ifdef DEBUG
  373. static void show_budge(void)
  374. {
  375.   char string[255];
  376.   int prev = flex_set_budge(1);
  377.   sprintf(string, "report Budge state = %d", prev);
  378.   flex_set_budge(prev);
  379.   _kernel_oscli(string);
  380. }
  381. #endif
  382.